using System;
using System.Collections.Generic;
using System.Linq;

namespace ICP_MS;

public class ColorMap
{
	public class ColorPoint
	{
		public byte r { get; set; }

		public byte g { get; set; }

		public byte b { get; set; }

		public double val { get; set; }

		public ColorPoint(byte red, byte green, byte blue, float value)
		{
			r = red;
			g = green;
			b = blue;
			val = value;
		}
	}

	private List<ColorPoint> colors = new List<ColorPoint>();

	private bool gradual = false;

	public List<ColorPoint> Colors => colors;

	public bool Gradual
	{
		get
		{
			return gradual;
		}
		set
		{
			gradual = value;
		}
	}

	public ColorMap()
	{
		colors.Clear();
		colors.Add(new ColorPoint(0, 0, byte.MaxValue, 0.125f));
		colors.Add(new ColorPoint(45, 150, byte.MaxValue, 0.25f));
		colors.Add(new ColorPoint(0, byte.MaxValue, byte.MaxValue, 0.375f));
		colors.Add(new ColorPoint(30, byte.MaxValue, 142, 0.5f));
		colors.Add(new ColorPoint(0, byte.MaxValue, 0, 0.625f));
		colors.Add(new ColorPoint(byte.MaxValue, byte.MaxValue, 0, 0.75f));
		colors.Add(new ColorPoint(byte.MaxValue, 128, 0, 0.875f));
		colors.Add(new ColorPoint(byte.MaxValue, 0, 0, 1f));
	}

	public void InitColors(double min, double max)
	{
		if (max == min)
		{
			max = min + 1.0;
		}
		for (int i = 0; i < colors.Count; i++)
		{
			colors[i].val = min + (double)(i + 1) * (max - min) / (double)colors.Count();
		}
	}

	public void GetColorAtValue(double value, ref byte red, ref byte green, ref byte blue)
	{
		for (int i = 0; i < colors.Count; i++)
		{
			ColorPoint currColor = colors[i];
			if (value < currColor.val)
			{
				if (gradual)
				{
					ColorPoint preColor = colors[Math.Max(0, i - 1)];
					double valueDiff = preColor.val - currColor.val;
					double fractBetween = ((valueDiff == 0.0) ? 0.0 : ((value - currColor.val) / valueDiff));
					red = (byte)((double)(preColor.r - currColor.r) * fractBetween + (double)(int)currColor.r);
					green = (byte)((double)(preColor.g - currColor.g) * fractBetween + (double)(int)currColor.g);
					blue = (byte)((double)(preColor.b - currColor.b) * fractBetween + (double)(int)currColor.b);
				}
				else
				{
					red = currColor.r;
					green = currColor.g;
					blue = currColor.b;
				}
				return;
			}
		}
		red = colors.Last().r;
		green = colors.Last().g;
		blue = colors.Last().b;
	}
}
